home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
001-025
/
scopedisk1
/
semaphorestutor
/
sigsem.c
< prev
Wrap
C/C++ Source or Header
|
1995-03-18
|
4KB
|
202 lines
/*
* This program plays around with signal semaphores...
*
* Thanks to C-A for providing the new bindings & AddSemaphore code
*
*/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/ports.h>
#include <exec/semaphores.h>
#include <exec/memory.h>
#include <exec/execbase.h>
struct XSSemaphore {
struct SignalSemaphore s;
WORD Users;
};
void *AllocMem();
void cleanup();
void DeleteSSemaphore();
struct SignalSemaphore *myFindSemaphore();
struct XSSemaphore *CreateSSemaphore();
struct XSSemaphore *sem = 0;
/* I made this extended semaphore so that there is an easy way to
* keep track of when it is safe to delete it. If anyone can think
* of a better way to do this, I'd love to hear it.
*/
extern int Enable_Abort;
main()
{
int i;
Enable_Abort = 0;
/* the existance check/creation must be atomic --> Forbid/Permit */
Forbid();
if (!(sem = (struct XSSemaphore *)myFindSemaphore("sigSemaphore")))
sem = CreateSSemaphore("sigSemaphore",0);
else
sem->Users++;
Permit();
if (!sem) {
printf("Error, can't find *or* create semaphore\n");
cleanup();
exit(100);
}
for (i=0;i<5;i++) {
/* get use of the semaphore */
ObtainSemaphore(sem);
/* we now have exclusive access */
printf("\nTask $%06x owns the semaphore\n",FindTask(0));
/* pretend to so some action requiring semaphore */
Delay(1 + (rand()&31));
printf("\t\t...semaphore now released\n");
/* yield control to someone else */
ReleaseSemaphore(sem);
/* pretend to so some action not requiring semaphore */
Delay(1 + (rand()&31));
}
cleanup();
}
void cleanup()
{
if (sem) {
/* the user check/delete must be atomic --> Forbid/Permit */
Forbid();
if (--sem->Users == 0)
DeleteSSemaphore(sem);
Permit();
sem = 0;
}
}
struct XSSemaphore *CreateSSemaphore(name,pri)
char *name;
int pri;
{
struct XSSemaphore *sem;
char *buf;
sem = AllocMem(sizeof(struct XSSemaphore), MEMF_PUBLIC|MEMF_CLEAR);
if (!sem) return(0);
sem->s.ss_Link.ln_Type = NT_SIGNALSEM;
sem->s.ss_Link.ln_Pri = pri;
/* Note that the name must be copied as the original creator
* of the semaphore might exit. We can't leave a pointer to
* the original data segment lying around after the program
* has exited.
*/
if (name) {
buf = AllocMem(strlen(name)+1, MEMF_PUBLIC);
if (!buf) {
FreeMem(sem, sizeof(struct XSSemaphore));
return(0);
}
strcpy(buf,name);
sem->s.ss_Link.ln_Name = buf;
myAddSemaphore(sem);
}
else
InitSemaphore(sem);
sem->Users = 1;
return(sem);
}
void DeleteSSemaphore(sem)
struct XSSemaphore *sem;
{
char *name;
if (!sem) return;
name = sem->s.ss_Link.ln_Name;
if (name) {
myRemSemaphore(sem);
FreeMem(name, strlen(name) + 1 );
}
FreeMem(sem, sizeof(struct XSSemaphore));
}
/* The bindings for "AddSemaphore" are broken in 1.2 Amiga.lib
*
* Dale's handcrafted AddSemaphore().
*/
myAddSemaphore(ss)
struct SignalSemaphore *ss;
{
extern struct ExecBase *SysBase;
InitSemaphore(ss);
Forbid();
Enqueue(&SysBase->SemaphoreList,ss);
Permit();
}
/* The "C" interface code for the following semaphore routines is broken in
* Amiga.lib and in the Aztec C release 3.4a.
*
* @ Lattice people should cut and paste the assembler into a separate file.
*/
#if AZTEC_C
#asm
; The exec.library function "AddSemaphore" is broken in KickStart rel. 33.180
;
; The Aztec bindings think that they should be using a0 to pass the
; argument instead of a1. This is likely the problem with the Lattice
; bindings. The Exec AddSemaphore function seems to be just plain broken.
;
; -Rico
XREF _SysBase
XREF _LVOFindSemaphore
XREF _LVORemSemaphore
XDEF _myFindSemaphore
XDEF _myRemSemaphore
_myFindSemaphore:
move.l 4(sp),a1
move.l _SysBase,a6
jmp _LVOFindSemaphore(a6)
_myRemSemaphore:
move.l 4(sp),a1
move.l _SysBase,a6
jmp _LVORemSemaphore(a6)
#endasm
#endif